#include <iostream>
#include <fstream>

#include "MetaData.h"
#include "Object.h"
#include "types/DataType.h"
#include "types/DataTypeFactory.h"
#include "RawDataInfo.h"

MetaData::MetaData( std::ifstream &infile, ObjectDefaults* objectDefaults, LeadIn *li )
    : infile( infile ), objectDefaults( objectDefaults ), leadIn( li ), objectCount()
{
    readObjectCount();

    for ( unsigned int i = 0; i < objectCount; ++i )
    {
        objects.push_back( new Object( infile, objectDefaults, leadIn ) );
    }
}

void MetaData::readObjectCount()
{
    infile.read(( char* )&objectCount, 4 );
    std::cout << "  cur leadin has " << objectCount << " object" << std::endl;
}

void MetaData::readRawData()
{
    int rawDataLen = leadIn->getNxtSegOffset() - leadIn->getDataOffset();
    int segDataLen = 0;

    for ( Object *obj : objects )
    {
        const DataType* dt = obj->getDataType();
        if( dt )
        {
            int dataLen = dt->getDatTypLen();
            if( dt->getTypeID() == 0x20 )       //string
            { dataLen = obj->getNBytes(); }

            segDataLen += dataLen * obj->getDimension() * obj->getNValue();
        }
    }
    int chunkSize = rawDataLen / segDataLen;
    if( rawDataLen % segDataLen != 0 )
    { chunkSize ++; }
    for( int i = 0; i < chunkSize; i++ )
    {
        for ( ObjectList::iterator object = objects.begin();
                object != objects.end(); ++object )
        {
            if ((*object )->hasRawData() )
            {
                (*object )->readRawData();
            }
        }
    }
}

void MetaData::print() const
{
    std::cout << "   Read meta data, print Object info: " << std::endl;
    std::cout << "        Contains " << objectCount << " objects." << std::endl;

    for( Object * obj : objects )
    {
        std::cout << "        cur object:          " << obj->getPath() << std::endl;
        RawDataInfo *rawDataInfo = obj->getRawDataInfo( obj->getPath() );
        if( rawDataInfo )
        {
            std::cout << "              type  :          " << rawDataInfo->dataType << std::endl;
            std::cout << "              nvalue:          " << rawDataInfo->nvalue << std::endl;
        }
    }
}

const MetaData::ObjectList& MetaData::getObjectList() const
{
    return objects;
}


